package com.anc.platform.model.platform.controller;


import com.alibaba.csp.sentinel.annotation.SentinelResource;
import com.anc.platform.config.CommonBlockHandler;
import com.anc.platform.config.CommonFallback;
import com.anc.platform.limit.RedisRaterLimiter;
import com.anc.platform.model.platform.biz.ScmLogisticsCompanyBizService;
import com.anc.platform.model.platform.entity.ScmLogisticsCompany;
import com.anc.platform.model.platform.model.param.PageAddOrderProductParam;
import com.anc.platform.model.platform.model.vo.ScmLogisticsCompanyVO;
import com.anc.platform.model.platform.service.IScmLogisticsCompanyService;
import com.anc.platform.model.platform.util.ScmLogisticsCompanyUtils;
import com.anc.platform.utils.ExceptionUtil;
import com.anc.redis.redis.RedisClient;
import com.baomidou.mybatisplus.autoconfigure.ConfigurationCustomizer;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.google.common.collect.Lists;
import exception.AncException;
import lombok.SneakyThrows;
import model.PageResult;
import model.Response;
import model.ResponseFactory;
import org.apache.commons.collections4.CollectionUtils;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.TransactionCallback;
import org.springframework.transaction.support.TransactionCallbackWithoutResult;
import org.springframework.transaction.support.TransactionTemplate;
import org.springframework.web.bind.annotation.*;

import util.JsonUtil;
import util.PageUtil;

import javax.annotation.Resource;
import javax.validation.Valid;
import java.util.List;
import java.util.concurrent.TimeUnit;

/**
 * <p>
 * 物流公司维护表 前端控制器
 * </p>
 *
 * @author Anc
 * @since 2022-07-02
 */
@RestController
@RequestMapping("/platform/scm-logistics-company")
public class ScmLogisticsCompanyController {
    @Autowired
    private ScmLogisticsCompanyBizService scmLogisticsCompanyBizService;
    @Autowired
    private IScmLogisticsCompanyService iScmLogisticsCompanyService;
    @Autowired
    private RedisClient redisClient;
    @Autowired
    private RedissonClient redissonClient;
    @Resource
    private TransactionTemplate transactionTemplate;
    @Autowired
    private RedisRaterLimiter redisRaterLimiter;
    @PostMapping("/add")
    public Response addMainCompanyInfo(@RequestBody  String param){
        System.out.println("34234");
        String token1 = redisRaterLimiter.acquireTokenFromBucket("XMALL"+ "ip地址", 10, 1000);
        System.out.println(token1);
        return ResponseFactory.buildSuccessResponse();
    }
    @GetMapping("/ttttt")
    public Response addMainCompanyInfo(){
        String token1 = redisRaterLimiter.acquireTokenFromBucket("XMALL"+ "ip地址", 10, 1000);
        System.out.println(token1);
        System.out.println("34234");
        return ResponseFactory.buildSuccessResponse();
    }
    public static void main(String[] args) {
        ScmLogisticsCompany scmLogisticsCompany=new ScmLogisticsCompany();
        scmLogisticsCompany.setLogisticCompanyCode("123");
        scmLogisticsCompany.setLogisticCompanyName("jingdong");
        System.out.println(JsonUtil.toJSon(scmLogisticsCompany));
    }

    /**
     * 申明式事务测试
     * @param logisticsCompanyType
     * @return
     * @throws InterruptedException
     */
    @RequestMapping("/test")
    public Response test(@RequestParam(value = "logisticsCompanyType", required = true) Integer logisticsCompanyType) throws InterruptedException {
        System.out.println("kaishi");
        ScmLogisticsCompany scmLogisticsCompany = new ScmLogisticsCompany();
        scmLogisticsCompany.setId("111111111");
        scmLogisticsCompany.setLogisticCompanyName("11111111");
        ScmLogisticsCompany scmLogisticsCompany1 = new ScmLogisticsCompany();
        scmLogisticsCompany1.setId("22222222222222");
        scmLogisticsCompany1.setLogisticCompanyName("222222222222");
        //不关心结果
        transactionTemplate.execute(new TransactionCallbackWithoutResult() {
            @SneakyThrows
            protected void doInTransactionWithoutResult(TransactionStatus status) {
                try {
                    iScmLogisticsCompanyService.save(scmLogisticsCompany);
                    int a=1/0;
                    iScmLogisticsCompanyService.save(scmLogisticsCompany1);
                } catch (Exception e) {
                    status.setRollbackOnly();
                    System.out.println("xxxx");
                    throw e;
                }
            }
        });

        //关心结果
//        Integer execute = transactionTemplate.execute(new TransactionCallback<Integer>() {
//            @Override
//            public Integer doInTransaction(TransactionStatus status) {
//                iScmLogisticsCompanyService.save(scmLogisticsCompany);
//
//                iScmLogisticsCompanyService.save(scmLogisticsCompany1);
//
//                return 1;
//            }
//        });

        return ResponseFactory.buildSuccessResponse("hello");
    }
    /**
     * 根据货运属性查询物流公司
     * Cacheable缓存测试  mybatis-plus测试
     * @param logisticsCompanyType
     * @return
     */
    @RequestMapping("/findlogisticsCompanyByType")
    public Response findlogisticsCompanyByType(@RequestParam(value = "logisticsCompanyType", required = true) Integer logisticsCompanyType) throws InterruptedException {
        if (logisticsCompanyType==null) {
            throw new AncException("货运属性参数为空");
        }
        List<ScmLogisticsCompanyVO> companyVOList = Lists.newArrayList();
        List<ScmLogisticsCompany> companyList = scmLogisticsCompanyBizService.findBytypeList(logisticsCompanyType);
        if (!CollectionUtils.isEmpty(companyList)) {
            companyList.forEach(files -> {
                companyVOList.add(ScmLogisticsCompanyUtils.entityToScmLogisticsCompanyDTO(files));
            });
        }
        //测试分页
        PageAddOrderProductParam param=new PageAddOrderProductParam();
        Page<ScmLogisticsCompany> page = PageUtil.toMybatisPlusPage(param);
        LambdaQueryWrapper<ScmLogisticsCompany> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(ScmLogisticsCompany::getLogisticType,1);
        IPage<ScmLogisticsCompany> page1 = iScmLogisticsCompanyService.page(page, wrapper);
        PageResult<ScmLogisticsCompany> scmLogisticsCompanyPageResult = PageUtil.convertResult(page, e -> e);
        //测试XML
        List<ScmLogisticsCompany> list=iScmLogisticsCompanyService.testFind(1);
        return ResponseFactory.buildSuccessResponse(companyVOList);
    }

    /**
     * 布隆过滤器测试
     * @param id
     * @return
     */
    @RequestMapping("/redisTest/{id}")
    public Response redisTest(@PathVariable("id") String id) {
        ScmLogisticsCompany byId = iScmLogisticsCompanyService.getById(id);
        redisClient.set(id,byId,60, TimeUnit.SECONDS);
        ScmLogisticsCompany scmLogisticsCompany =(ScmLogisticsCompany) redisClient.get(id);
        return  ResponseFactory.buildSuccessResponse(scmLogisticsCompany);
    }

    /**
     * redis 分布式缓存测试
     * @param id
     * @return
     */
    @RequestMapping("/redissonTest")
    public Response redissonTest(@RequestParam(value = "id", required = true) String id) {
        ScmLogisticsCompany byId=new ScmLogisticsCompany();
        //竞争的锁对象名称
        RLock lock = redissonClient.getLock("lockName");
        //tryLock可以不加参数，不会抛异常，仅尝试获取一次锁对象
        //tryLock(5,10,TimeUnit.SECONDS)意思为等待锁对象5秒钟，获取到对象10秒钟后释放锁对象，调用此方法会抛出异常
        if (lock.tryLock()){
            try {
                byId = iScmLogisticsCompanyService.getById("1");
                Thread.sleep(1);
            } catch (InterruptedException e) {
                e.printStackTrace();
            } finally {
                //lock.isLocked()误区：此方法不是判断当前线程是否被锁定，而是判断该锁对象当前是否被任意线程所持有。
                // 所以不能使用if(lock.isLocked()){lock.unlock();}的写法来释放锁。
                lock.unlock();
                System.out.println("shifang");
            }
        }

        return  ResponseFactory.buildSuccessResponse(byId);
    }

    @RequestMapping("/feignTest")
    public Response feignTest(@RequestParam(value = "id", required = true) String id) {
        scmLogisticsCompanyBizService.updateForFeign(id);
        return  ResponseFactory.buildSuccessResponse(null);
    }

    @RequestMapping("/feignTestSentinel")
    @SentinelResource(value = "feignTestSentinel",  fallback = "fallback",
            fallbackClass = ExceptionUtil.class,  blockHandler = "handleException",
            blockHandlerClass = ExceptionUtil.class  )
    public Response feignTestSentinel(@RequestParam(value = "id", required = true) String id) {
        scmLogisticsCompanyBizService.updateForFeign(id);
        return  ResponseFactory.buildSuccessResponse(null);
    }
    @RequestMapping("/info/{id}")
    @SentinelResource(value = "info",
            blockHandlerClass = CommonBlockHandler.class,
            blockHandler = "handleException2",
            fallbackClass = CommonFallback.class,
            fallback = "fallback"
    )
    public Response info(@PathVariable("id") Integer id){


        return ResponseFactory.buildSuccessResponse("sdfsdfs");
    }
}

